package com.schedualnew.mq.config;

import cn.hutool.json.JSONUtil;
import com.ewell.sdk.business.EwellServiceTool;
import com.ewell.sdk.business.MessageHandler;
import com.ewell.sdk.domain.MessageEntity;
import com.ewell.sdk.exception.SDKException;
import com.schedualnew.mq.constvalue.ExamStatusEnum;
import com.schedualnew.mq.dto.esb.ChangeExaminationStatusMsg;
import com.schedualnew.mq.dto.esb.dict.dept.NoticeDeptChangeMsg;
import com.schedualnew.mq.dto.esb.dict.exam.NoticeExamItemChangeMsg;
import com.schedualnew.mq.dto.esb.dict.user.NoticeUserChangeMsg;
import com.schedualnew.mq.dto.esb.receive.ReceiveESBEntry;
import com.schedualnew.mq.dto.esb.receive.refund.ReceiveRefundEsbEntry;
import com.schedualnew.mq.dto.exam.autoschedule.ExamApplyItemBaseInfoDto;
import com.schedualnew.mq.service.ApplyService;
import com.schedualnew.mq.service.CommonService;
import com.schedualnew.mq.service.ScheduleServiceImpl;
import com.schedualnew.mq.service.XRayService;
import com.schedualnew.mq.util.JacksonUtil;
import com.schedualnew.mq.util.JsonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author ljy aka ryan
 * @date 2022/6/15 9:17
 * @description TODO
 */
@Configuration      //1.主要用于标记配置类，兼备Component的效果。
public class StaticScheduleTask {

    private Logger logger = LogManager.getLogger(StaticScheduleTask.class);

    @Autowired
    private AppParamsConfig paramsConfig;

    @Autowired
    private XRayService xRayService;

    @Autowired
    private ApplyMQConfig applyMQConfig;

    @Autowired
    private ApplyService applyService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private EwellServiceTool ewellServiceTool;

    @Autowired
    private XRayMQConfig xRayMQConfig;

    @Autowired
    private ScheduleServiceImpl scheduleService;

    @Value("${applymq.isTest}")
    private String isTest;

    //ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    // 监听申请单状态改变
    ThreadPoolExecutor examStatusChangeExecutor = null;
    // 监听新申请单
    ThreadPoolExecutor examApplyNewExecutor = null;
    // 监听检查项目字典变化
    ThreadPoolExecutor examItemChangeExecutor = null;
    // 监听检查科室字典变化
    ThreadPoolExecutor deptChangeExecutor = null;
    // 监听检查项目字典变化
    ThreadPoolExecutor userChangeExecutor = null;

    /**
     * 启动之后执行 监听申请单状态改变MQ
     */
    @PostConstruct
    public void mqListenExamStatusChange() {
        try {
            String key = String.format("%s_%s_%s", paramsConfig.getListenExaminationStatusChangeMMQ(),
                    paramsConfig.getListenExaminationStatusChangeMQ(),
                    paramsConfig.getSourceSystemCode());
            if ("1".equals(isTest)) {
                return;
            }

            if (paramsConfig.getListenExaminationStatusChangeEnable()) {
                examStatusChangeExecutor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
                try {
                    MessageHandler messageHandler = new MessageHandler(examStatusChangeExecutor) {
                        @Override
                        public void onMessage(MessageEntity messageEntity) throws Throwable {
                            try {
                                // 使用线程池处理消息
                                try {
                                    // logger.info("mqListenExamStatusChange:" + key + "\r\n     " + JSONUtil.toJsonStr(messageEntity));
                                    String refundNotice = "<REQUISITION_STATUS_CODE>04</REQUISITION_STATUS_CODE>";

                                    if (StringUtils.isNotBlank(messageEntity.getMsg()) && messageEntity.getMsg().contains(refundNotice)) {
                                        // logger.info("退费处理:{}", messageEntity.getMsg());
                                        // 退费特殊处理
                                        ReceiveRefundEsbEntry esbEntry = JacksonUtil.readXmlValue(messageEntity.getMsg(), ReceiveRefundEsbEntry.class);
                                        if (Objects.nonNull(esbEntry) && Objects.nonNull(esbEntry.getMsgInfo())
                                                && Objects.nonNull(esbEntry.getMsgInfo().getMsg())
                                                && CollectionUtils.isNotEmpty(esbEntry.getMsgInfo().getMsg().getDetail())) {
                                            for (Map<String, Object> detail : esbEntry.getMsgInfo().getMsg().getDetail()) {
                                                ChangeExaminationStatusMsg statusMsg = JSONUtil.toBean(JSONUtil.toJsonStr(detail), ChangeExaminationStatusMsg.class);
                                                // logger.info("退费处理-statusMsg:" + JSONUtil.toJsonStr(statusMsg));
                                                String statusCode = statusMsg.getREQUISITION_STATUS_CODE();

                                                ExamStatusEnum type = ExamStatusEnum.getByStatusCode(statusCode);
                                                if (Objects.isNull(type)) {
                                                    logger.error("退费状态不需要处理:{}", JSONUtil.toJsonStr(statusMsg));
                                                }
                                                // 更新数据库状态
                                                commonService.changeExamStatus(statusMsg);
                                            }
                                        } else {
                                            logger.error("退费处理 没有找到消息内容:{}", JSONUtil.toJsonStr(esbEntry));
                                        }
                                    } else {
                                        ReceiveESBEntry esbEntry = JacksonUtil.readXmlValue(messageEntity.getMsg(), ReceiveESBEntry.class);
                                        // logger.info("mqListenExamStatusChange-status:" + JSONUtil.toJsonStr(esbEntry));

                                        if (Objects.nonNull(esbEntry)) {
                                            for (Object data : esbEntry.getMsgInfo().getMsg()) {
                                                ChangeExaminationStatusMsg statusMsg = JSONUtil.toBean(JSONUtil.toJsonStr(data), ChangeExaminationStatusMsg.class);
                                                // logger.info("statusMsg:" + JSONUtil.toJsonStr(statusMsg));
                                                String statusCode = statusMsg.getREQUISITION_STATUS_CODE();

                                                // 申请单登记 - 创建虚拟预约记录改变 申请单状态
                                                if ("05".equals(statusCode)) {
                                                    try {
                                                        // 插入虚拟的预约数据
                                                        String hospCode = esbEntry.getMessageHeader().getHospCode();
                                                        // 保存预约信息
                                                        commonService.saveScheduleItem(statusMsg, hospCode);
                                                    } catch (Exception e) {
                                                        logger.error("mqListenExamStatusChange-saveScheduleItem-" + statusCode + "\r\n" + JSONUtil.toJsonStr(statusMsg), e);
                                                    }
                                                } else {
                                                    ExamStatusEnum type = ExamStatusEnum.getByStatusCode(statusCode);
                                                    if (Objects.isNull(type)) {
                                                        logger.error("状态不需要处理:{}", JSONUtil.toJsonStr(statusMsg));
                                                    }
                                                    // 更新数据库状态
                                                    commonService.changeExamStatus(statusMsg);
                                                }
                                            }
                                        } else {
                                            logger.error("mqListenExamStatusChange消息处理失败:消息内容为空!");
                                        }
                                    }
                                } catch (Exception e) {
                                    logger.error("mqListenExamStatusChange消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                                }
                            } catch (Exception e) {
                                logger.error("mqListenExamStatusChange消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                            }
                        }

                        @Override
                        public void onException(Throwable throwable, MessageEntity messageEntity) {
                            logger.error("mqListenExamStatusChange接收消息异常:" + paramsConfig.getListenExaminationStatusChangeMMQ() + "---" + paramsConfig.getListenExaminationStatusChangeMQ() + "  " + JSONUtil.toJsonStr(messageEntity), throwable);
                        }
                    };
                    logger.info("mqListenExamStatusChange-listenReceiveMessage:{}", key);
                    ewellServiceTool.buildTopicListener(paramsConfig.getListenExaminationStatusChangeMMQ(),
                            paramsConfig.getListenExaminationStatusChangeMQ(),
                            false, 1, 10,
                            messageHandler);
                } catch (SDKException e) {
                    logger.error("mqListenExamStatusChange监听队列消息失败:" + key, e);
                }
            } else {
                logger.info("监听申请单状态改变:未启动! {}", JSONUtil.toJsonStr(paramsConfig));
            }
        } catch (Exception e) {
            logger.error("configureTasks:", e);
        }
    }


    /**
     * 启动之后执行 监听申请单申请
     */
    @PostConstruct
    public void mqListenExamApply() {
        String methodName = "mqListenExamApply";
        String key = String.format("%s_%s_%s",
                applyMQConfig.getQueueManagerName(),
                applyMQConfig.getQueueName(),
                applyMQConfig.getSourceSystemCode());
        if (applyMQConfig.isEnable()) {
            examApplyNewExecutor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
            try {
                logger.info(methodName + ":" + key);
                try {
                    MessageHandler messageHandler = new MessageHandler(examApplyNewExecutor) {
                        @Override
                        public void onMessage(MessageEntity messageEntity) throws Throwable {
                            try {
                                // 使用线程池处理消息
                                try {
                                    // logger.info("预约申请监听到消息:" + key + "\r\n     " + JSONUtil.toJsonStr(messageEntity));
                                    if (!StringUtils.isEmpty(messageEntity.getMsg())) {
                                        applyService.handleApplyMsg(messageEntity.getMsg(), messageEntity.getMsgId(), applyMQConfig.getQueueManagerName(), "");
                                    }
                                } catch (Exception e) {
                                    logger.error("预约申请消息处理失败:" + e.getMessage(), e);
                                }
                            } catch (Exception e) {
                                logger.error("消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                            }
                        }

                        @Override
                        public void onException(Throwable throwable, MessageEntity messageEntity) {
                            logger.error(methodName + "接收消息异常:" + JSONUtil.toJsonStr(messageEntity), throwable);
                        }
                    };
                    logger.info(methodName + ":{}", key);
                    ewellServiceTool.buildTopicListener(applyMQConfig.getQueueManagerName(),
                            applyMQConfig.getQueueName(), false, 1, 10,
                            messageHandler);

                } catch (SDKException e) {
                    logger.error("监听队列消息失败:" + key, e);
                }
            } catch (Exception e) {
                logger.error("configureTasks:", e);
            }
        } else {
            logger.info(methodName + ":配置不监听申请单:{}", JSONUtil.toJsonStr(applyMQConfig));
        }
    }

    /**
     * 监听检查项目字典变化
     */
    @PostConstruct
    public void mqListenExamItemChange() {
        String methodName = "mqListenExamItemChange";
        try {
            String MMQ = paramsConfig.getListenExamItemChangeMMQ();
            String MQ = paramsConfig.getListenExamItemChangeMQ();
            Boolean isEnable = paramsConfig.getListenExamItemChangeEnable();
            String key = String.format("%s_%s", MMQ, MQ);
            // 判断是否启用
            if (isEnable) {
                examItemChangeExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
                try {
                    MessageHandler messageHandler = new MessageHandler(examItemChangeExecutor) {
                        @Override
                        public void onMessage(MessageEntity messageEntity) throws Throwable {
                            try {
                                // 使用线程池处理消息
                                try {
                                    logger.info(methodName + ":" + key + "\r\n     " + JSONUtil.toJsonStr(messageEntity));

                                    ReceiveESBEntry esbEntry = JacksonUtil.readXmlValue(messageEntity.getMsg(), ReceiveESBEntry.class);
                                    logger.info(methodName + "-status:" + JSONUtil.toJsonStr(esbEntry));
                                    String hospCode = esbEntry.getMessageHeader().getHospCode();
                                    List<Object> realMsg = esbEntry.getMsgInfo().getMsg();
                                    List<NoticeExamItemChangeMsg> examItemChangeMsgs = JSONUtil.toList(JSONUtil.toJsonStr(realMsg), NoticeExamItemChangeMsg.class);
                                    // 更新数据库状态
                                    commonService.createOrUpdateExamItem(examItemChangeMsgs, hospCode);
                                } catch (Exception e) {
                                    logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                                }
                            } catch (Exception e) {
                                logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                            }
                        }

                        @Override
                        public void onException(Throwable throwable, MessageEntity messageEntity) {
                            logger.error(methodName + "接收消息异常:" + key + "  " + JSONUtil.toJsonStr(messageEntity), throwable);
                        }
                    };
                    logger.info(methodName + "-listenReceiveMessage:{}", key);
                    // 执行监听
                    ewellServiceTool.buildTopicListener(MMQ,
                            MQ,
                            false, 1, 10,
                            messageHandler);
                } catch (SDKException e) {
                    logger.error(methodName + "监听队列消息失败:" + key, e);
                }
            } else {
                logger.info(methodName + ":配置不监听检查项目变更:{}", JSONUtil.toJsonStr(paramsConfig));
            }
        } catch (Exception e) {
            logger.error(methodName + ":", e);
        }
    }

    /**
     * 监听检查科室字典变化
     */
    @PostConstruct
    public void mqListenDeptChange() {
        String methodName = "mqListenDeptChange";
        try {
            String MMQ = paramsConfig.getListenDeptChangeMMQ();
            String MQ = paramsConfig.getListenDeptChangeMQ();
            Boolean isEnable = paramsConfig.getListenDeptChangeEnable();
            String key = String.format("%s_%s", MMQ, MQ);
            // 判断是否启用
            if (isEnable) {
                deptChangeExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
                try {
                    MessageHandler messageHandler = new MessageHandler(deptChangeExecutor) {
                        @Override
                        public void onMessage(MessageEntity messageEntity) throws Throwable {
                            try {
                                // 使用线程池处理消息
                                try {
                                    logger.info(methodName + key + "\r\n     " + JSONUtil.toJsonStr(messageEntity));

                                    ReceiveESBEntry esbEntry = JacksonUtil.readXmlValue(messageEntity.getMsg(), ReceiveESBEntry.class);
                                    logger.info(methodName + "-status:" + JSONUtil.toJsonStr(esbEntry));
                                    String hospCode = esbEntry.getMessageHeader().getHospCode();
                                    List<Object> realMsg = esbEntry.getMsgInfo().getMsg();
                                    List<NoticeDeptChangeMsg> deptChangeMsgs = JSONUtil.toList(JSONUtil.toJsonStr(realMsg), NoticeDeptChangeMsg.class);
                                    // 更新数据库状态
                                    commonService.createOrUpdateDeptInfo(deptChangeMsgs, hospCode);

                                } catch (Exception e) {
                                    logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                                }
                            } catch (Exception e) {
                                logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                            }
                        }

                        @Override
                        public void onException(Throwable throwable, MessageEntity messageEntity) {
                            logger.error(methodName + "接收消息异常:" + key + "  " + JSONUtil.toJsonStr(messageEntity), throwable);
                        }
                    };
                    logger.info(methodName + "-listenReceiveMessage:{}", key);
                    ewellServiceTool.buildTopicListener(paramsConfig.getListenUserChangeMMQ(),
                            paramsConfig.getListenUserChangeMQ(),
                            false, 1, 10,
                            messageHandler);
                } catch (SDKException e) {
                    logger.error(methodName + "监听队列消息失败:" + key, e);
                }
            } else {
                logger.info(methodName + ":配置不监听科室字典变更:{}", JSONUtil.toJsonStr(paramsConfig));
            }
        } catch (Exception e) {
            logger.error(methodName + ":", e);
        }
    }


    /**
     * 监听职工变化
     */
    @PostConstruct
    public void mqListenUserChange() {
        String methodName = "mqListenUserChange";
        try {
            String MMQ = paramsConfig.getListenUserChangeMMQ();
            String MQ = paramsConfig.getListenUserChangeMQ();
            Boolean isEnable = paramsConfig.getListenUserChangeEnable();
            String key = String.format("%s_%s", MMQ, MQ);

            // 判断是否启用
            if (isEnable) {
                userChangeExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
                try {
                    MessageHandler messageHandler = new MessageHandler(userChangeExecutor) {
                        @Override
                        public void onMessage(MessageEntity messageEntity) throws Throwable {
                            try {
                                // 使用线程池处理消息
                                try {
                                    logger.info(methodName + key + "\r\n     " + JSONUtil.toJsonStr(messageEntity));

                                    ReceiveESBEntry esbEntry = JacksonUtil.readXmlValue(messageEntity.getMsg(), ReceiveESBEntry.class);
                                    logger.info(methodName + "-status:" + JSONUtil.toJsonStr(esbEntry));
                                    String hospCode = esbEntry.getMessageHeader().getHospCode();
                                    List<Object> realMsg = esbEntry.getMsgInfo().getMsg();
                                    List<NoticeUserChangeMsg> userChangeMsgs = JSONUtil.toList(JSONUtil.toJsonStr(realMsg), NoticeUserChangeMsg.class);
                                    // 更新数据库状态
                                    commonService.createOrUpdateUserInfo(userChangeMsgs, hospCode);

                                } catch (Exception e) {
                                    logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                                }
                            } catch (Exception e) {
                                logger.error(methodName + "消息处理失败:" + JSONUtil.toJsonStr(messageEntity), e);
                            }
                        }

                        @Override
                        public void onException(Throwable throwable, MessageEntity messageEntity) {
                            logger.error(methodName + "接收消息异常:" + key + "  " + JSONUtil.toJsonStr(messageEntity), throwable);
                        }
                    };
                    logger.info(methodName + "-listenReceiveMessage:{}", key);
                    ewellServiceTool.buildTopicListener(paramsConfig.getListenUserChangeMMQ(),
                            paramsConfig.getListenUserChangeMQ(),
                            false, 1, 10,
                            messageHandler);
                } catch (SDKException e) {
                    logger.error(methodName + "监听队列消息失败:" + key, e);
                }
            } else {
                logger.info(methodName + ":配置不监听职工变更:{}", JSONUtil.toJsonStr(paramsConfig));
            }
        } catch (Exception e) {
            logger.error(methodName + ":", e);
        }
    }


    /**
     * 定时拉取 放射科号源
     */
    @Scheduled(cron = "${xray-room.scheduleTime:0 0/3 * * * ? }")
    public void getPACSSourceCount() {
        try {
            if (xRayMQConfig.getEnable()) {
                logger.info("开始执行放射科号源拉取任务.....");
                xRayService.getXRaySource();
                logger.info("拉取放射科号源任务执行完成");
            } else {
                logger.info("放射科号源拉取任务不执行!");
            }
        } catch (Exception e) {
            logger.error("放射科号源拉取任务执行异常:" + e.getMessage(), e);
        }
    }

    /**
     * 定时拉取 放射科号源
     */
    @Scheduled(cron = "${xray-room.cs.source.scheduleTime:0 0/3 * * * ? }")
    public void getCSSourceCount() {
        try {
            if (xRayMQConfig.getCs().getSource().getEnable()) {
                logger.info("开始执行超声号源拉取任务.....");
                xRayService.getCSSource();
                logger.info("拉取超声号源任务执行完成");
            } else {
                logger.info("超声号源拉取任务不执行!");
            }
        } catch (Exception e) {
            logger.error("超声号源拉取任务执行异常:" + e.getMessage(), e);
        }
    }


    ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    /**
     * 定时执行自动预约任务
     */
    @Scheduled(cron = "${applymq.auto-schedule.timer-task-corn:0 0/5 * * * ?}")
    public void autoScheduleTask() {
        try {
            // 查询半小时以内所有未预约的申请单，如果同一类型的检查有多个申请单不进行自动预约
            List<ExamApplyItemBaseInfoDto> applies = scheduleService.getNoScheduledApplies(applyMQConfig.getAutoSchedule().getTimerTask());
            if (CollectionUtils.isNotEmpty(applies)) {
                // 根据患者和检查类别分组
                Map<String, List<ExamApplyItemBaseInfoDto>> groupApplies = applies.stream()
                        .collect(Collectors.groupingBy(x -> x.getSickId() + "_" + x.getExamClass()));
                for (String sickId : groupApplies.keySet()) {
                    List<ExamApplyItemBaseInfoDto> dtos = groupApplies.get(sickId);
                    // 申请单为空或者一个检查类别有多个申请单 就直接跳过
                    if (CollectionUtils.isNotEmpty(dtos) && dtos.size() == 1) {
                        ExamApplyItemBaseInfoDto applyItemBaseInfoDto = dtos.get(0);
                        try {
                            List<AutoScheduleProperties.AutoScheduleConfigItem> configItems = applyMQConfig.getAutoSchedule().getConfigItems();
                            if (CollectionUtils.isNotEmpty(configItems)) {
                                AutoScheduleProperties.AutoScheduleConfigItem configItem = configItems.stream()
                                        // 执行科室
                                        .filter(x -> x.getPerformDept().contains(applyItemBaseInfoDto.getPerformDept()))
                                        // 检查项目code
                                        .filter(y -> y.getItemCodes().contains(applyItemBaseInfoDto.getItemCode()))
                                        // 患者来源 如果没配置就不过滤
                                        .filter(y -> CollectionUtils.isEmpty(y.getSource()) || y.getSource().contains(applyItemBaseInfoDto.getPatientSource()))
                                        // 患者优先级 如果没配置就不过滤
                                        .filter(y -> CollectionUtils.isEmpty(y.getPriority()) || y.getPriority().contains(applyItemBaseInfoDto.getPriorityOrder()))
                                        .findFirst().orElse(null);
                                // 需要自动预约的，创建新的线程进行预约操作，不然影响数据入库
                                if (Objects.nonNull(configItem)) {
                                    // 加入到队列里面进行自动预约操作
                                    executor.execute(() -> {
                                        try {
                                            logger.info("自动预约，开始预约:{}", applyItemBaseInfoDto.getApplyNo());
                                            applyService.autoSchedule(applyItemBaseInfoDto.getApplyNo());
                                            logger.info("自动预约，完成预约:{}", applyItemBaseInfoDto.getApplyNo());
                                        } catch (Exception e) {
                                            logger.error("自动预约 autoSchedule，error:" + JsonUtil.toJson(applyItemBaseInfoDto), e);
                                        } finally {
                                            logger.info("自动预约，结束:{}", applyItemBaseInfoDto.getApplyNo());
                                        }
                                    });
                                    // 每条待预约数据都睡眠1秒，防止多线程执行器死亡
                                    Thread.sleep(1500);
                                }
                            }
                        } catch (Exception e) {
                            logger.error("执行自动预约异常:" + JsonUtil.toJson(applyItemBaseInfoDto), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("自动预约异常:" + e.getMessage(), e);
        }
    }


    /**
     * 类被回收 停止线程执行器
     */
    protected void finalize() {
        try {
            if (Objects.nonNull(examStatusChangeExecutor)) {
                examStatusChangeExecutor.shutdown();
            }
            if (Objects.nonNull(examApplyNewExecutor)) {
                examApplyNewExecutor.shutdown();
            }
            if (Objects.nonNull(examItemChangeExecutor)) {
                examItemChangeExecutor.shutdown();
            }
            if (Objects.nonNull(deptChangeExecutor)) {
                deptChangeExecutor.shutdown();
            }
            if (Objects.nonNull(userChangeExecutor)) {
                userChangeExecutor.shutdown();
            }
        } catch (Exception e) {
            logger.error("finalize:" + e.getMessage(), e);
        } finally {
            examStatusChangeExecutor = null;
            examApplyNewExecutor = null;
            examItemChangeExecutor = null;
            deptChangeExecutor = null;
            userChangeExecutor = null;
        }
    }
}
